#pragma once
#include <vector>
#include <fstream>

using namespace std;

#define DIM 2
#define T_Type int
#define POINT_SIZE 5

#define FILE_ID	12345678
#define OBJ_POINT	1
#define OBJ_LINE	2
#define OBJ_TRI     3
#define OBJ_END		9999

extern void gdiDrawLine(T_Type x0, T_Type y0, T_Type x1, T_Type y1);

class CObj
{
protected:
	int m_type;
public:
	void DrawLine(T_Type x0, T_Type y0, T_Type x1, T_Type y1)
	{
		gdiDrawLine(x0, y0, x1, y1);
	}
	virtual void Save(fstream  &f)
	{
		f << m_type << " ";
	}
	virtual void Load(fstream  &f) { };
	virtual void Draw()
	{
	}
};

class CMyPoint : public CObj
{
protected:
	T_Type m_pt[DIM];

public:
	CMyPoint()
	{
		m_type = OBJ_POINT;
	}
	void SetPoint(T_Type x, T_Type y)
	{
		m_pt[0] = x;
		m_pt[1] = y;
	}
	virtual void Draw()
	{
		T_Type size = POINT_SIZE;
		DrawLine(m_pt[0] - size, m_pt[1], m_pt[0] + size, m_pt[1]);
		DrawLine(m_pt[0], m_pt[1] - size, m_pt[0], m_pt[1] + size);
	}
	virtual void Save(fstream &f)
	{
		CObj::Save(f);
		f << m_pt[0] << " " << m_pt[1] << endl;
	}
	virtual void Load(fstream &f)
	{
		f >> m_pt[0] >> m_pt[1];
	}
};

class CMyLine : public CObj
{
protected:
	T_Type m_pt[2][DIM];
public:
	CMyLine()
	{
		m_type = OBJ_LINE;
	}
	void SetPoint(int i, T_Type x, T_Type y)
	{
		m_pt[i][0] = x;
		m_pt[i][1] = y;
	}
	virtual void Draw()
	{
		DrawLine(m_pt[0][0], m_pt[0][1], m_pt[1][0], m_pt[1][1]);
	}
	virtual void Save(fstream &f)
	{
		CObj::Save(f);
		f << m_pt[0][0] << " " << m_pt[0][1] << " " << m_pt[1][0] << " " << m_pt[1][1] << endl;
	}
	virtual void Load(fstream &f)
	{
		f >> m_pt[0][0] >> m_pt[0][1] >> m_pt[1][0] >> m_pt[1][1];
	}
};

class CMyTri : public CObj
{
protected:
	T_Type m_pt[3][DIM];
public:
	CMyTri()
	{
		m_type = OBJ_TRI;
	}
	void SetPoint(int i, T_Type x, T_Type y)
	{
		m_pt[i][0] = x;
		m_pt[i][1] = y;
	}
	virtual void Draw()
	{

		DrawLine(m_pt[0][0], m_pt[0][1], m_pt[1][0], m_pt[1][1]);
		DrawLine(m_pt[1][0], m_pt[1][1], m_pt[2][0], m_pt[2][1]);
		DrawLine(m_pt[2][0], m_pt[2][1], m_pt[0][0], m_pt[0][1]);
	}
	virtual void Save(fstream &f)
	{
		CObj::Save(f);
		f << m_pt[0][0] << " " << m_pt[0][1] << " " << m_pt[1][0] << " " << m_pt[1][1] << " " << m_pt[2][0] << " " << m_pt[2][1] << endl;
	}
	virtual void Load(fstream &f)
	{
		f >> m_pt[0][0] >> m_pt[0][1] >> m_pt[1][0] >> m_pt[1][1];
	}
};



class CMyGraph
{
protected:
	vector<CObj *> m_list;
public:
	CMyGraph();
	~CMyGraph();
	void Clear()
	{
		int i;
		CObj *v;
		int size = m_list.size();
		for (i = 0; i < size; i++)
		{
			v = m_list[i];
			delete v;
		}
		m_list.clear();
	}
	void InsertObj(CObj *obj)
	{
		m_list.push_back(obj);
	}
	void Draw()
	{
		int i;
		CObj *v;
		int size = m_list.size();
		for (i = 0; i < size; i++)
		{
			v = m_list[i];
			v->Draw();
		}
	}
	void Save(fstream &f)
	{
		int i;
		CObj *v;
		f << FILE_ID << endl;
		int size = m_list.size();
		for (i = 0; i < size; i++)
		{
			v = m_list[i];
			v->Save(f);
		}
		f << OBJ_END;
	}
	void Load(fstream &f)
	{
		int id;
		CMyPoint *myPoint;
		CMyLine *myLine;

		f >> id;
		if (id != FILE_ID)
			return; // error

		f >> id;
		while (id != OBJ_END)
		{
			switch (id)
			{
			case OBJ_POINT:
				myPoint = new CMyPoint;
				myPoint->Load(f);
				InsertObj(myPoint);
				break;
			case OBJ_LINE:
				myLine = new CMyLine;
				myLine->Load(f);
				InsertObj(myLine);
				break;
			}
			f >> id;
		}
	}
};


